using CalcSharp.Core;
using CalcSharp.Core.Containers;
using ZedGraph;

namespace CalcSharp
{
    sealed class ploter
    {
        private ploter() { }
        private static int PlotType(string typ)
        {
            switch (typ.ToUpper())
            {
                case "CURVE":
                    return 0;
                case "BAR":
                    return 1;
                case "PIE":
                    return 2;
                default:
                    return -1;
            }
        }

        public static void doplot(string formula, double min, double max, double stepp)
        {
            double points = (max - min) / stepp;
            if (points > 15000) throw new CSException("Too many data points");
            ReversePolishNotation r = new ReversePolishNotation();
            double point;
            double x, y;
            PointPairList l = new PointPairList();
            point = min;
            while (point <= max)
            {
                x = point;
                Program.loaded.Mem["$x"] = point;
                r.Parse(formula);
                y = r.Evaluate();
                l.Add(x, y);
                point += stepp;
            }
            plot plotwin = new plot();
            plotwin.Text = "Diagram - " + formula;
            plotwin.MdiParent = Program.loaded.Parent;
            plotwin.Curve(l, formula);
            plotwin.Show();
        }

        public static void plot_data(string[] param)
        {
            int i;
            PointPairList pts;
            plot plotwin;
            if (Program.loaded.Mtrx_mem.isset(param[1]))
            {
                AMatrix m = Program.loaded.Mtrx_mem[param[1]];
                if (m.Columns != 2) throw new CSException("Only matrixes with 2 columns can be drawn");
                pts = new PointPairList();
                for (i = 0; i < m.Rows; i++) pts.Add(m[i, 0], m[i, 1]);
                plotwin = new plot();
                plotwin.Text = "Diagram of datapair: " + param[1];
                plotwin.MdiParent = Program.loaded.Parent;
                if (param.Length > 2)
                {
                    int type = PlotType(param[2]);
                    if (type == 0) plotwin.Curve(pts, param[1]);
                    else if (type == 1) plotwin.Bar(pts, param[1]);
                    else if (type == 2) throw new CSException("Pie type only supported on single sets");
                    else throw new CSException("Unrecognised diagram type. Type can be curve, bar, pie");
                }
                else plotwin.Curve(pts, param[1]);
                plotwin.Show();
            }
            else if (param.Length > 2)
            {
                if (Program.loaded.Set_mem.isset(param[1]) && Program.loaded.Set_mem.isset(param[2]))
                {
                    ASet tmp1 = Program.loaded.Set_mem[param[1]];
                    ASet tmp2 = Program.loaded.Set_mem[param[2]];
                    pts = new PointPairList();
                    for (i = 0; i < tmp1.Count; i++) pts.Add(tmp1[i], tmp2[i]);
                    plotwin = new plot();
                    plotwin.Text = "Diagram of Sets: " + param[1] + " & " + param[2];
                    plotwin.MdiParent = Program.loaded.Parent;
                    if (param.Length > 3)
                    {
                        int type = PlotType(param[3]);
                        if (type == 0) plotwin.Curve(pts, param[1] + " & " + param[2]);
                        else if (type == 1) plotwin.Bar(pts, param[1] + " & " + param[2]);
                        else if (type == 2) throw new CSException("Pie type only supported on single sets");
                        else throw new CSException("Unrecognised diagram type. Type can be curve, bar, pie");
                    }
                    else plotwin.Curve(pts, param[1] + " & " + param[2]);
                    plotwin.Show();
                }
            }
            else if (Program.loaded.Set_mem.isset(param[1]))
            {
                ASet tmp = Program.loaded.Set_mem[param[1]];
                pts = new PointPairList();
                for (i = 0; i < tmp.Count; i++) pts.Add(i, tmp[i]);
                plotwin = new plot();
                plotwin.Text = "Diagram of Set: " + param[1];
                plotwin.MdiParent = Program.loaded.Parent;
                if (param.Length > 2)
                {
                    int type = PlotType(param[2]);
                    if (type == 0) plotwin.Curve(pts, param[1]);
                    else if (type == 1) plotwin.Bar(pts, param[1]);
                    else if (type == 2) plotwin.Pie(tmp.ToArray());
                    else throw new CSException("Unrecognised diagram type. Type can be curve, bar, pie");
                }
                else plotwin.Curve(pts, param[1]);
                plotwin.Show();
            }
        }
    }
}